#pragma once
#include "../Compiler/ast.h"
#include "compiler.h"
#include "../Compiler/error.h"
#define register 
using namespace XScript::Compile::Errors;
using namespace XScript::Runtime::BaseTypes;
using namespace XScript::Compile::Ast;
using namespace XScript::Compile;
typedef RawString Identifier;
extern int yylex();
/*
static int
file_input(char *buf, int max_size)
{
	if (feof(yyin))
	{
		return 0;
	}
	for (int len = 0; len < max_size; len++)
	{
		int ch;
		ch = getc(yyin);
		if (ch == EOF)
		{
			return len;
		}
		buf[len] = ch;
	}
}

static char **st_source_string;
static int st_current_source_line;
static int st_current_char_index;

void
xs_set_source_string(char **source)
{
	st_source_string = source;
	st_current_source_line = 0;
	st_current_char_index = 0;
}

static int
string_input(char *buf, int max_size)
{
	int len;
	if (st_source_string[st_current_source_line] == NULL)
	{
		return 0;
	}
	if (st_source_string[st_current_source_line][st_current_char_index] == '\0')
	{
		st_current_source_line++;
		st_current_char_index = 0;
	}
	if (st_source_string[st_current_source_line] == NULL)
	{
		return 0;
	}
	len = smaller(strlen(st_source_string[st_current_source_line]) - st_current_char_index, max_size);
	strncpy(buf, &st_source_string[st_current_source_line][st_current_char_index], len);
	st_current_char_index += len;
	return len;
}

static int
my_yyinput(char *buf, int max_size)
{
	int	result = file_input(buf, max_size);

	return result;
}*/

static inline int
file_input(char *buf, int max_size)
{
	if (feof(yyin))
	{
		return 0;
	}
	for (int len = 0; len < max_size; len++)
	{
		int ch;
		ch = getc(yyin);
		if (ch == EOF)
		{
			return len;
		}
		buf[len] = ch;
	}
}

static inline int
my_yyinput(char *buf, int max_size)
{
	int	result = file_input(buf, max_size);

	return result;
}

inline Compiler GetCurrentCompiler()
{
	return CompilerTag::GetCurrent();
}

inline size_t GetLineNumber()
{
	return CompilerTag::GetCurrent()->current_line_number;
}

inline void xscriptcall IncrementLineNumber()
{
	CompilerTag::GetCurrent()->current_line_number++;
}

void xscriptcall
AppendToStringBuffer(const char letter);

RawString xscriptcall
FlushStringBuffer();

RawString xscriptcall
CreateIdentifier(const char *str);

DeclarationList xscriptcall 
ChainDeclaration(DeclarationList list,
	Declaration decl);

TypeSpecifier xscriptcall
CreateTypeSpecifier(RuntimeBasicType type);

void xscriptcall
AddFunctionDefine(RuntimeBasicType type,
	RawString identifier,
	ParameterList parameter_list,
	Block block);

Parameter xscriptcall
CreateParameter(RuntimeBasicType type,
	RawString identifier);

ParameterList xscriptcall
CreateParameterList(Parameter pram);

ParameterList xscriptcall
ChainParameter(ParameterList list,
	Parameter p);

ArgumentList xscriptcall
CreateArgumentList(Expression expression);

ArgumentList xscriptcall
ChainArgumentList(ArgumentList list, Argument alg);

StatementList xscriptcall
CreateStatementList(Statement statement);

StatementList xscriptcall
ChainStatementList(StatementList list,
	Statement statement);

CommaExpression xscriptcall
CreateCommaExpression(Expression left,
	Expression right);

AssignExpresion xscriptcall
CreateAssignExpression(Expression left,
	AssignmentOperator _operator,
	Expression operand);

BinaryExpression xscriptcall
CreateMathBinaryExpression(MathBinaryExpressionOperator _operator,
	Expression left,
	Expression right);

BinaryExpression xscriptcall
CreateCompareBinaryExpression(CompareBinaryExpressionOperator _operator,
	Expression left,
	Expression right);

BinaryExpression xscriptcall
CreateLogicBinaryExpression(LogicBinaryExpressionOperator _operator,
	Expression left,
	Expression right);

MinusExpression xscriptcall
CreateMinusExpression(Expression operand);

LogicalNotExpression xscriptcall
CreateLogicalNotExpression(Expression operand);

IncdecExpression xscriptcall
CreateIncDecExpression(Expression operand,
	IncDecExpressionOprator inc_or_dec);

IdentifierExpression xscriptcall
CreateIdentifierExpression(RawString identifier);

FunctionCallExpression xscriptcall
CreateFunctionCallExpression(Expression function,
	ArgumentList argument);

ConstantExpression xscriptcall
CreateBooleanExpression(Boolean value);

ConstantExpression xscriptcall
CreateInt32Expression(Int32 value);

ConstantExpression xscriptcall
CreateDoubleExpression(Double value);

ConstantExpression xscriptcall
CreateStringExpression(RawString value);

IfStatement xscriptcall
CreateIfStatement(Expression condition,
	Block then_block, ElsifList elsif_list,
	Block else_block);

ElsifList xscriptcall
ChainElsifList(ElsifList list, Elsif add);

Elsif xscriptcall
CreateElsif(Expression expr, Block block);

WhileStatement xscriptcall
CreateWhileStatement(RawString label,
	Expression condition, Block block);

ForStatement xscriptcall
CreateForStatement(RawString label,
	Expression init,
	Expression cond,
	Expression post,
	Block block);

ForeachStatement xscriptcall
CreateForeachStatement(RawString label,
	RawString variable,
	Expression collection,
	Block block);

Block xscriptcall
OpenBlock();

Block xscriptcall
CloseBlock(Block block, StatementList statement_list);

ExpressionStatement xscriptcall
CreateExpressionStatement(Expression expression);

ReturnStatement xscriptcall
CreateReturnStatement(Expression expression);

BreakStatement xscriptcall
CreateBreakStatement(RawString label);

ContinueStatement xscriptcall
CreateContinueStatement(RawString label);

TryStatement xscriptcall
CreateTryStatement(Block try_block,
	RawString exception,
	Block catch_block,
	Block finally_block);

ThrowStatement xscriptcall
CreateThrowStatement(Expression expression);

DeclarationStatement xscriptcall
CreateDeclarationStatement(RuntimeBasicType type,
	RawString identifier,
	Expression initializer);

ElsifList xscriptcall
CreateElsifLsit(Elsif elsif);

